'use strict';

define(['fn'], (fn) => {
    var s = (selector, parent) => (parent || document).querySelector(selector);
    var sall = (selector, parent) => Array.from((parent || document).querySelectorAll(selector));
    var e = (tag, attrs, childs, events) => {
        var element = document.createElement(tag);
        if (attrs != null) fn.each(attrs, (v, a) => v == null ? null : element[fn.camelize(a)] = v);
        if (childs != null) childs.forEach(c => c == null ? null : element.appendChild(c));
        if (events != null) fn.each(events, (v, e) => v == null ? null : element.addEventListener(e, v));
        return element;
    };
    var replace_element = (old_element, new_element) => (old_element.parentElement.replaceChild(new_element, old_element), new_element);
    var clear_element = element => Array.from(element.childNodes).forEach(e => e.remove());

    var animate = (element, animation) => {
        element.classList.add(animation);
        window.getComputedStyle(element).opacity;      // flush. 
        element.classList.remove(animation);
    }

    var make_delayed_append = (container, default_animation, delay) => {
        if (delay == null) delay = 50;

        var queue = [];

        var schedule = () => {
            if (queue.length === 0) return;
            var item = queue.shift();

            container.appendChild(item.element);
            if (item.animation != null) animate(item.element, item.animation);

            if (queue.length === 0) return;
            setTimeout(schedule, delay);
        };

        return (element, animation) => {
            if (animation == null) animation = default_animation;
            queue.push({ element, animation });
            if (queue.length === 1) setTimeout(schedule, delay);
        };
    }

    var make_checkbox = attrs => {
        var element = e('button', { class_name: 'checkbox', type: 'button' });
        var cl = element.classList;
        var class_existence = class_ => ({
            get: () => cl.contains(class_),
            set: (exist) => exist ? cl.add(class_) : cl.remove(class_),
        });
        Object.defineProperties(element, {
            value: class_existence('checked'),
            readOnly: {
                get: () => element.disabled,
                set: x => element.disabled = x,
            },
            placeholder: {
                get: () => element.textContent,
                set: x => element.textContent = x,
            },
        });
        if (attrs != null) fn.each(attrs, (v, a) => v == null ? null : element[fn.camelize(a)] = v);
        element.addEventListener('click', () => element.value = !element.value);
        return element;
    };


    return (api) => {
        // overlay control
        var overlay = (() => {
            var overlay_element = s('.overlay');
            var overlay_wrapper = s('.overlay > .wrapper');

            var cancelable = false;
            var ov = (element) => {
                var cl = overlay_element.classList;
                var show = cl.contains('show');
                if (element == null) {  // hide overlay
                    if (!show) throw 'unable to hide already hidden overlay';
                    clear_element(overlay_wrapper);
                    cancelable = false;
                }
                else {                  // show overlay
                    if (show) throw 'unable to show already shown overlay';
                    overlay_wrapper.appendChild(element);
                    animate(element, 'slide-up');
                }
                cl.toggle('show');
            }

            overlay_wrapper.addEventListener('click', ev => {
                if (!cancelable) return;
                if (ev.target !== overlay_wrapper) return;
                overlay();
            });

            var make_input = spec => {
                if (spec.type === 'check') {
                    return make_checkbox({ name: spec.id, placeholder: spec.label, value: spec.value });
                }

                var element = e('input', { name: spec.id, type: spec.type, placeholder: spec.label, value: spec.value, class_name: spec.code ? "code" : null });
                return element;
            };

            ov.form = spec => {
                var form = e('form', { id: 'overlay-popup-form', class_name: 'form' });
                if (spec.title) form.appendChild(e('div', { class_name: 'title', text_content: spec.title }));

                // make inputs
                var focus;
                var inputs = [];
                var checks = [];
                var inits  = [];
                spec.inputs.forEach(input => {
                    // skip null
                    if (input == null) return;

                    // text message
                    if (typeof input === 'string') {
                        form.appendChild(e('p', { text_content: input }));
                        return;
                    }

                    // form input
                    var element = make_input(input);
                    form.appendChild(element);
                    inputs.push(element);
                    checks.push(input.check);
                    if (spec.must_modify) inits.push(input.value);
                    else inits.push(null);
                    if (focus == null || input.focus) focus = element;
                });

                // make error display and busy spinner
                var result = form.appendChild(e('div', { class_name: 'result' }));
                form.appendChild(e('div', { class_name: 'spinner' }, [
                    e('div', { class_name: 'spinning' }),
                ]));

                // make action buttons
                if (spec.action) {
                    // form prompt
                    form.appendChild(e('div', { class_name: 'actions' }, [
                        e('input', { type: 'button', value: '取消' }, null, { click: () => overlay() }),
                        e('input', { type: 'submit', value: spec.action_text||'确定' }),
                    ]));

                    var report = error => {
                        if (error == null) return overlay();
                        cancelable = true;
                        form.classList.remove('busy');
                        form.classList.add('error');
                        result.textContent = error;
                        inputs.forEach(input => input.readOnly = false);
                    };

                    form.addEventListener('submit', ev => {
                        ev.preventDefault();
                        if (form.classList.contains('busy')) return;
                        form.classList.add('busy');
                        cancelable = false;
                        inputs.forEach(input => input.readOnly = true);

                        // validate
                        var values = inputs.map(input => input.value);
                        var value_map = {};
                        values.forEach((x, i) => value_map[inputs[i].name] = x);
                        for (var i in values) {
                            var input = inputs[i];
                            var value = values[i];
                            var label = input.placeholder;
                            var check = checks[i] || (() => null);
                            var check_changed = x => x === inits[i] ? `请修改${label}` : check(x, value_map);
                            var check_required = x => x === '' ? `请填写${label}` : check_changed(x);
                            var error = check_required(value);
                            if (error != null) {
                                report(error);
                                input.focus();
                                return;
                            }
                        }

                        spec.action(value_map, report);
                    });
                }
                else {
                    // message prompt
                    form.appendChild(e('div', { class_name: 'actions' }, [
                        focus = e('input', { type: 'submit', value: '知道了' }, null, { click: () => overlay() }),
                    ]));
                    form.addEventListener('submit', ev => ev.preventDefault());
                }

                overlay(form);
                cancelable = true;
                if (focus != null) setTimeout(() => focus.focus(), 100);
            }

            ov.popup = text =>
                overlay(e('div', {
                    class_name: 'popup normal-cursor',
                    text_content: text,
                }));

            ov.prompt = (text, action_text, action) =>
                ov.form({
                    action_text,
                    action,
                    inputs: [text],
                })

            return ov;
        })();

        // various views/dialogs
        var register = () => {
            overlay.form({
                title: "注册",
                action_text: "注册",
                inputs: [
                    {
                        id: 'username',
                        label: '用户名',
                        type: 'text',
                        check: x => x.length > 48 ? "用户名长度不能超过48个字符" : null,
                        focus: true,
                        code: true,
                    },
                    {
                        id: 'password',
                        label: '密码',
                        type: 'password',
                        check: x => x.length > 48 ? "密码长度不能超过48个字符" : null,
                    },
                    {
                        id: 'password-again',
                        label: '密码（再一次）',
                        type: 'password',
                        check: (x, xs) => x != xs.password ? "两次密码应相同" : null,
                    },
                    {
                        id: 'name',
                        label: '真实姓名',
                        type: 'text',
                        check: x => x.length > 48 ? "真实姓名长度不能超过48个字符" : null,
                    },
                    {
                        id: 'phone',
                        label: '手机号码',
                        type: 'text',
                        check: x => x.length > 24 ? "手机号码长度不能超过24个字符" : null,
                        code: true,
                    },
                    "请务必填写有效的手机号码。在您预约车辆后，我们将通过这个手机号码与您取得联系。",
                ],
                action: (values, report) => {
                    api.user_add(values.username, values.password, values.name, values.phone, error => {
                        if (error != null) return report(error);
                        report();
                        login("注册成功，请登录。", values.username);
                    });
                }
            });
        };

        var login = (message, username, remember) => {
            overlay.form({
                title: "登录",
                action_text: "登录",
                inputs: [
                    message,
                    {
                        id: 'username',
                        label: '用户名',
                        type: 'text',
                        value: username,
                        check: x => x.length < 48 ? null : "用户名长度不能超过48个字符",
                        focus: username == null,
                        code: true,
                    },
                    {
                        id: 'password',
                        label: '密码',
                        type: 'password',
                        check: x => x.length < 48 ? null : "密码长度不能超过48个字符",
                        focus: username != null,
                    },
                    "若您忘记密码，请联系客服。",
                    {
                        id: 'remember',
                        label: '下次自动登录',
                        type: 'check',
                        value: remember == null ? true : remember,
                    },
                ],
                action: (values, report) => {
                    api.login(values.username, values.password, error => {
                        if (error != null) {
                            if (error === 'auth failed') error = "密码错误";
                            else if (error.endsWith('no such username')) error = "用户名不存在";
                            report(error);
                            return;
                        }
                        if (values.remember) localStorage.token = api.token;
                        setup_user();
                        report();
                    });
                }
            });
        };

        var logout = (no_popup) => {
            api.logout();
            delete localStorage.token;
            if (!no_popup) overlay.prompt("您已安全登出。");
            setup_user();
        };

        var make_dashboard_entry = (label, value, action, code) => {
            var element = e('div', { class_name: 'entry' }, [
                e('label', { text_content: label }),
            ]);
            var button = e('button', { text_content: value, disabled: action == null, class_name: code ? "code" : null }, null, {
                click: action == null ? null : () => action(x => button.textContent = x),
            });
            element.appendChild(button);
            return element;
        }
        var dashboard = () => {
            var container = e('div', { class_name: 'dashboard outlined' }, [
                e('div', {
                    class_name: 'title',
                    text_content: (api.role === 'admin' ? "管理员" : "用户") + "个人中心",
                }),
            ]);

            var append = make_delayed_append(container, 'slide-left')

            append(make_dashboard_entry('用户名', api.username, null, true));
            append(make_dashboard_entry('密码', '设置新密码', () => {
                overlay.form({
                    title: "设置新密码",
                    action_text: "设置新密码",
                    inputs: [
                        {
                            id: 'password',
                            label: '新密码',
                            type: 'password',
                            check: x => x.length > 48 ? "密码长度不能超过48个字符" : null,
                        },
                        {
                            id: 'password-again',
                            label: '新密码（再一次）',
                            type: 'password',
                            check: (x, xs) => x != xs.password ? "两次新密码应相同" : null,
                        },
                    ],
                    action: (values, report) => {
                        api.user_password_self(values.password, error => {
                            if (error != null) return report(error);
                            var username = api.username;
                            var remember = (localStorage.token != null);
                            logout(true);
                            report();
                            login("已设置新密码，请重新登录。", username, remember);
                        });
                    }
                });
            }));
            if (api.role === 'user') {
                append(make_dashboard_entry('真实姓名', api.name, change => {
                    overlay.form({
                        title: "修改真实姓名",
                        action_text: "修改真实姓名",
                        must_modify: true,
                        inputs: [
                            {
                                id: 'name',
                                label: '真实姓名',
                                type: 'text',
                                value: api.name,
                                check: x => x.length > 48 ? "真实姓名长度不能超过48个字符" : null,
                            },
                        ],
                        action: (values, report) => {
                            api.user_name_self(values.name, error => {
                                if (error != null) return report(error);
                                api.name = values.name;
                                change(values.name);
                                s('nav .profile > div').textContent = values.name;
                                report();
                            });
                        }
                    });
                }));
                append(make_dashboard_entry('手机号码', api.phone, change => {
                    overlay.form({
                        title: "修改手机号码",
                        action_text: "修改手机号码",
                        must_modify: true,
                        inputs: [
                            {
                                id: 'phone',
                                label: '手机号码',
                                type: 'text',
                                value: api.phone,
                                code: true,
                                check: x => x.length > 24 ? "手机号码长度不能超过24个字符" : null,
                            },
                            "请务必填写有效的手机号码。在您预约车辆后，我们将通过这个手机号码与您取得联系。",
                        ],
                        action: (values, report) => {
                            api.user_phone_self(values.phone, error => {
                                if (error != null) return report(error);
                                api.phone = values.phone;
                                change(values.phone);
                                report();
                            });
                        }
                    });
                }, true));
            }
            select_page(null, container);
        };

        // pages data
        var make_list_page = spec => {
            if (spec.list == null) return e('div', { text_content: '暂未开通' });   // FIXME: remove this
            var actions = e('div', { class_name: 'actions' }, [
                (spec.add == null ? null : e('button', {
                    type: 'button',
                    text_content: spec.add.label || `添加${spec.name}`,
                    class_name: 'action',
                }, null, { click: () => spec.add.action() })),
                e('button', { type: 'button', text_content: "刷新" }, null, {
                    click: fn.throttle(() => refresh(), 200),
                }),
                e('input', { type: 'text', placeholder: "搜索" }, null, {
                    input: fn.throttle(ev => search(ev.target.value), 500),
                }),
            ]);

            var wrapper = e('div', { class_name: 'wrapper' });

            var spinner = e('div', { class_name: 'spinner' }, [e('div', { class_name: 'spinning' })]);
            var more = e('button', { type: 'button', class_name: 'more', text_content: '继续加载' }, [], { click: () => load_more() });

            var container = e('div', { class_name: 'list' }, [ actions, wrapper, spinner, more ]);
            var cl = container.classList;
            Object.defineProperties(container, {
                busy: {
                    get: () => cl.contains('busy'),
                    set: busy => busy ? cl.add('busy') : cl.remove('busy'),
                },
                more: {
                    get: () => !more.disabled,
                    set: has_more => {
                        more.disabled = !has_more;
                        more.textContent = (has_more ? "继续加载" : "没有了");
                    },
                },
            });

            var next;
            var search_keyword = "";
            var refresh = () => {
                next = spec.list(search_keyword)();
                wrapper = replace_element(wrapper, e('div', { class_name: 'wrapper' }));
                container.busy = false;
                container.more = true;
                load_more();
            };

            var search = keyword => {
                search_keyword = keyword;
                refresh();
            };

            var load_more = () => {
                if (container.busy) return;
                if (!container.more) return;
                container.busy = true;
                var w = wrapper;
                var append = make_delayed_append(w, 'slide-left');
                next(items => {
                    if (wrapper !== w) return;
                    if (items == null) {
                        container.busy = false;
                        container.more = false;
                        overlay.prompt("载入失败");
                        return;
                    }
                    items.map(spec.format).forEach(element => append(element));
                    container.busy = false;
                    if (items.length < 10) container.more = false;
                })
            };

            refresh();
            container.refresh = refresh;
            return container;
        };
        var pages = [
            // admin
            {
                name: "用户",
                role: 'admin',
                list: api.user_list,
                format: item => e('div', { class_name: 'item item-user outlined' }, [
                    e('div', { class_name: 'profile' }, [
                        e('div', { class_name: 'name', text_content: item.name }),
                        e('div', { class_name: 'username code', text_content: item.username }),
                    ]),
                    e('div', { class_name: 'side' }, [
                        e('div', { class_name: 'phone code', text_content: item.phone }),
                        e('button', { class_name: 'password', text_content: "设置新密码" }, null, {
                            click: () => {
                                overlay.form({
                                    title: "设置新密码",
                                    action_text: "设置新密码",
                                    inputs: [
                                        `设置 ${item.name}（${item.username}） 的新密码`,
                                        {
                                            id: 'password',
                                            label: '新密码',
                                            type: 'password',
                                            check: x => x.length > 48 ? "密码长度不能超过48个字符" : null,
                                        },
                                        {
                                            id: 'password-again',
                                            label: '新密码（再一次）',
                                            type: 'password',
                                            check: (x, xs) => x != xs.password ? "两次新密码应相同" : null,
                                        },
                                    ],
                                    action: (values, report) => {
                                        api.user_password(item.id, values.password, error => {
                                            if (error != null) return report(error);
                                            report();
                                            overlay.prompt(`已为用户 ${item.name}（${item.username}） 设置了新密码。`);
                                        });
                                    }
                                });
                            },
                        }),
                    ]),
                ]),
            },
            {
                name: "快讯",
                role: 'admin',
                list: api.news_list,
                format: item => e('div', { class_name: 'item item-news outlined' }, [
                    e('div', { class_name: 'main' }, [
                        e('div', { class_name: 'date code', text_content: item.date }),
                        e('div', { class_name: 'body', text_content: item.body }),
                    ]),
                    e('div', { class_name: 'side' }, [
                        e('button', { text_content: "修改" }, null, {
                            click: ev => {
                                var body_element = s('.main > .body', ev.target.parentElement.parentElement);
                                overlay.form({
                                    title: "修改快讯",
                                    action_text: "修改快讯",
                                    must_modify: true,
                                    inputs: [
                                        item.date,
                                        {
                                            id: 'body',
                                            label: '正文',
                                            type: 'text',
                                            value: item.body,
                                        },
                                    ],
                                    action: (values, report) => {
                                        api.news_body(item.id, values.body, error => {
                                            if (error != null) return report(error);
                                            report();
                                            body_element.textContent = values.body;
                                            item.body = values.body;
                                        });
                                    }
                                });
                            },
                        }),
                        e('button', { text_content: "删除" }, null, {
                            click: ev => {
                                var item_element = ev.target.parentElement.parentElement;
                                overlay.form({
                                    title: "删除快讯",
                                    action_text: "删除快讯",
                                    inputs: [
                                        item.date,
                                        item.body,
                                        "确定要删除么？",
                                    ],
                                    action: (values, report) => {
                                        api.news_remove(item.id, error => {
                                            if (error != null) return report(error);
                                            report();
                                            item_element.remove();
                                        });
                                    }
                                });
                            },
                        }),
                    ]),
                ]),
                add: {
                    action: () => overlay.form({
                        title: "添加快讯",
                        action_text: "添加快讯",
                        inputs: [
                            {
                                id: 'body',
                                label: '正文',
                                type: 'text',
                            },
                        ],
                        action: (values, report) => {
                            var refresh = active_page.refresh;
                            api.news_add(values.body, error => {
                                if (error != null) return report(error);
                                report();
                                refresh();
                            });
                        }
                    }),
                },
            },
            {
                name: "车辆",
                role: 'admin',
                list: api.auto_list,
                format: item => e('div', { class_name: 'item item-auto outlined' }, [
                    e('div', { class_name: 'main' }, [
                        e('div', { class_name: 'name', text_content: item.name }),
                        e('div', { class_name: 'description', text_content: item.description }),
                    ]),
                    e('div', { class_name: 'side' }, [
                        e('div', { class_name: 'price code' + (item.available === 'true' ? "" : " unavailable"), text_content: item.price }),
                        e('button', { text_content: "下架" }, null, {
                            click: ev => {
                                var item_element = ev.target.parentElement.parentElement;
                                overlay.form({
                                    title: "下架",
                                    action_text: "下架",
                                    inputs: [
                                        `车辆名称：${item.name}`,
                                        `车辆描述：${item.description}`,
                                        `租赁参考价：￥${item.price}/日`,
                                        item.available === 'true' ? null : "（车辆已租出。）",
                                        "该操作无法撤销！下架不影响现有订单。确定要下架么？",
                                    ],
                                    action: (values, report) => {
                                        api.auto_remove(item.id, error => {
                                            if (error != null) return report(error);
                                            report();
                                            item_element.remove();
                                        });
                                    }
                                });
                            },
                        }),
                    ]),
                ]),
                add: {
                    action: () => overlay.form({
                        title: "添加车辆",
                        action_text: "添加车辆",
                        inputs: [
                            {
                                id: 'name',
                                label: '车辆名称',
                                type: 'text',
                            },
                            {
                                id: 'description',
                                label: '车辆描述',
                                type: 'text',
                            },
                            {
                                id: 'price',
                                label: '租赁参考价（￥/日）',
                                type: 'text',
                                code: true,
                                check: x => !x.match(/\d+/) ? "价格必须是正整数"
                                    : parseInt(x) > 1e9 ? "价格不应超过一亿元"
                                    : parseInt(x) < 1 ? "价格应为正整数" : null,
                            },
                        ],
                        action: (values, report) => {
                            var refresh = active_page.refresh;
                            api.auto_add(values.name, values.description, values.price, error => {
                                if (error != null) return report(error);
                                report();
                                refresh();
                            });
                        },
                    }),
                },
            },
            {
                name: "订单",
                role: 'admin',
                list: api.order_list,
                format: item => e('div', { class_name: 'item item-order outlined ' + item.state }, [
                    e('div', { class_name: 'main' }, [
                        e('div', { class_name: 'orderer code', text_content: item.orderer }),
                        e('div', { class_name: 'phone code', text_content: item.phone }),
                        e('div', { class_name: 'name', text_content: item.auto_name }),
                        e('div', { class_name: 'description', text_content: item.auto_description }),
                    ]),
                    e('div', { class_name: 'side' }, [
                        e('div', { class_name: 'price code', text_content: item.price }),
                        e('div', { class_name: 'state' }),
                        e('button', { class_name: 'deliver', text_content: "租出" }, null, {
                            click: ev => {
                                var item_cl = ev.target.parentElement.parentElement.classList;
                                overlay.form({
                                    title: "租出",
                                    action_text: "标记为已租出",
                                    inputs: [
                                        `租赁者：${item.orderer}`,
                                        `租赁者手机号码：${item.phone}`,
                                        `车辆名称：${item.auto_name}`,
                                        `车辆描述：${item.auto_description}`,
                                        `租赁参考价：￥${item.price}/日`,
                                        "该操作无法撤销！确定要标记订单为已租出么？",
                                    ],
                                    action: (values, report) => {
                                        api.order_deliver(item.id, error => {
                                            if (error != null) return report(error);
                                            report();
                                            item_cl.remove(item.state);
                                            item_cl.add(item.state = 'delivered');
                                        });
                                    }
                                });
                            },
                        }),
                        e('button', { class_name: 'return', text_content: "归还" }, null, {
                            click: ev => {
                                var item_cl = ev.target.parentElement.parentElement.classList;
                                overlay.form({
                                    title: "归还",
                                    action_text: "标记为已归还",
                                    inputs: [
                                        `租赁者：${item.orderer}`,
                                        `租赁者手机号码：${item.phone}`,
                                        `车辆名称：${item.auto_name}`,
                                        `车辆描述：${item.auto_description}`,
                                        `租赁参考价：￥${item.price}/日`,
                                        "该操作无法撤销！确定要标记订单为已归还么？",
                                    ],
                                    action: (values, report) => {
                                        api.order_return(item.id, error => {
                                            if (error != null) return report(error);
                                            report();
                                            item_cl.remove(item.state);
                                            item_cl.add(item.state = 'returned');
                                        });
                                    }
                                });
                            },
                        }),
                        e('button', { class_name: 'cancel', text_content: "取消" }, null, {
                            click: ev => {
                                var item_cl = ev.target.parentElement.parentElement.classList;
                                overlay.form({
                                    title: "取消订单",
                                    action_text: "取消该订单",
                                    inputs: [
                                        `租赁者：${item.orderer}`,
                                        `租赁者手机号码：${item.phone}`,
                                        `车辆名称：${item.auto_name}`,
                                        `车辆描述：${item.auto_description}`,
                                        `租赁参考价：￥${item.price}/日`,
                                        "该操作无法撤销！确定要取消该订单么？",
                                    ],
                                    action: (values, report) => {
                                        api.order_cancel(item.id, error => {
                                            if (error != null) return report(error);
                                            report();
                                            item_cl.remove(item.state);
                                            item_cl.add(item.state = 'canceled');
                                        });
                                    }
                                });
                            },
                        }),
                    ]),
                ]),
            },
            {
                name: "反馈",
                role: 'admin',
                list: api.feedback_list,
                format: item => e('div', { class_name: 'item item-feedback outlined' }, [
                    e('div', { class_name: 'main' }, [
                        e('div', { class_name: 'who code', text_content: item.who }),
                        e('div', { class_name: 'body', text_content: item.body }),
                        e('div', { class_name: 'reply' + (item.reply == null ? " hide" : ""), text_content: item.reply == null ? "" : item.reply }),
                    ]),
                    e('div', { class_name: 'side' }, [
                        e('button', { text_content: (item.reply == null ? "" : "修改") + "回复" }, null, {
                            click: ev => {
                                var button_element = ev.target;
                                var reply_element = s('.main > .reply', ev.target.parentElement.parentElement);
                                var title = (item.reply == null ? "" : "修改") + "回复";
                                overlay.form({
                                    title: title,
                                    action_text: title,
                                    must_modify: true,
                                    inputs: [
                                        `${item.body}`,
                                        {
                                            id: 'reply',
                                            label: '回复',
                                            type: 'text',
                                            value: item.reply,
                                        },
                                    ],
                                    action: (values, report) => {
                                        api.feedback_reply(item.id, values.reply, error => {
                                            if (error != null) return report(error);
                                            report();
                                            reply_element.textContent = values.reply;
                                            reply_element.classList.remove('hide');
                                            button_element.textContent = "修改回复";
                                            item.reply = values.reply;
                                        });
                                    }
                                });
                            },
                        }),
                    ]),
                ]),
            },

            // user
            {
                name: "快讯",
                role: 'user',
                list: api.news_list,
                format: item => e('div', { class_name: 'item item-news outlined' }, [
                    e('div', { class_name: 'main' }, [
                        e('div', { class_name: 'date code', text_content: item.date }),
                        e('div', { class_name: 'body', text_content: item.body }),
                    ]),
                ]),
            },
            {
                name: "车辆",
                role: 'user',
                list: api.auto_list_available,
                format: item => e('div', { class_name: 'item item-auto outlined' }, [
                    e('div', { class_name: 'main' }, [
                        e('div', { class_name: 'name', text_content: item.name }),
                        e('div', { class_name: 'description', text_content: item.description }),
                    ]),
                    e('div', { class_name: 'side' }, [
                        e('div', { class_name: 'price code', text_content: item.price }),
                        e('button', { text_content: "租用" }, null, {
                            click: ev => {
                                var item_element = ev.target.parentElement.parentElement;
                                overlay.form({
                                    title: "租用车辆",
                                    action_text: "下单",
                                    inputs: [
                                        `车辆名称：${item.name}`,
                                        `车辆描述：${item.description}`,
                                        `租赁参考价：￥${item.price}/日`,
                                        "请确认您填写的手机号码，并保持您的手机畅通。",
                                        `您的手机号码：${api.phone}（可以在个人中心修改）`,
                                        "下单后我们将火速与您取得联系，以便确定价格、收货地址和租赁时长。",
                                    ],
                                    action: (values, report) => {
                                        api.order_add(item.id, error => {
                                            if (error != null) return report(error);
                                            report();
                                            item_element.remove();
                                            overlay.prompt("下单成功。您可以在“订单”页面查看或取消该订单。")
                                        });
                                    }
                                });
                            },
                        }),
                    ]),
                ]),
            },
            {
                name: "订单",
                role: 'user',
                list: api.order_list_self,
                format: item => e('div', { class_name: 'item item-order outlined ' + item.state }, [
                    e('div', { class_name: 'main' }, [
                        e('div', { class_name: 'name', text_content: item.auto_name }),
                        e('div', { class_name: 'description', text_content: item.auto_description }),
                    ]),
                    e('div', { class_name: 'side' }, [
                        e('div', { class_name: 'price code', text_content: item.price }),
                        e('div', { class_name: 'state' }),
                        e('button', { class_name: 'cancel', text_content: "取消" }, null, {
                            click: ev => {
                                var item_cl = ev.target.parentElement.parentElement.classList;
                                overlay.form({
                                    title: "取消订单",
                                    action_text: "取消该订单",
                                    inputs: [
                                        `车辆名称：${item.auto_name}`,
                                        `车辆描述：${item.auto_description}`,
                                        `租赁参考价：￥${item.price}/日`,
                                        "该操作无法撤销！确定要取消该订单么？",
                                    ],
                                    action: (values, report) => {
                                        api.order_cancel_self(item.id, error => {
                                            if (error != null) return report(error);
                                            report();
                                            item_cl.remove(item.state);
                                            item_cl.add(item.state = 'canceled');
                                        });
                                    }
                                });
                            },
                        }),
                    ]),
                ]),
            },
            {
                name: "反馈",
                role: 'user',
                list: api.feedback_list_self,
                format: item => e('div', { class_name: 'item item-feedback outlined' }, [
                    e('div', { class_name: 'main' }, [
                        e('div', { class_name: 'body', text_content: item.body }),
                        e('div', { class_name: 'reply' + (item.reply == null ? " hide" : ""), text_content: item.reply == null ? "" : item.reply }),
                    ]),
                    e('div', { class_name: 'side' }, [
                        e('button', { text_content: "删除" }, null, {
                            click: ev => {
                                var item_element = ev.target.parentElement.parentElement;
                                overlay.form({
                                    title: "删除反馈",
                                    action_text: "删除反馈",
                                    inputs: [
                                        `反馈正文：${item.body}`,
                                        item.reply == null ? "（还未得到回复）" : `回复：${item.reply}`,
                                        "确定要删除么？",
                                    ],
                                    action: (values, report) => {
                                        api.feedback_remove_self(item.id, error => {
                                            if (error != null) return report(error);
                                            report();
                                            item_element.remove();
                                        });
                                    }
                                });
                            },
                        }),
                    ]),
                ]),
                add: {
                    label: '我要反馈',
                    action: () => overlay.form({
                        title: "反馈",
                        action_text: "提交反馈",
                        inputs: [
                            "您对我们的网站有什么意见或建议？",
                            {
                                id: 'body',
                                label: '反馈',
                                type: 'text',
                            },
                        ],
                        action: (values, report) => {
                            var refresh = active_page.refresh;
                            api.feedback_add(values.body, error => {
                                if (error != null) return report(error);
                                report();
                                refresh();
                            });
                        }
                    }),
                },
            },

            // guest
            {
                name: "快讯",
                list: api.news_list,
                format: item => e('div', { class_name: 'item item-news outlined' }, [
                    e('div', { class_name: 'main' }, [
                        e('div', { class_name: 'date code', text_content: item.date }),
                        e('div', { class_name: 'body', text_content: item.body }),
                    ]),
                ]),
            },
            {
                name: "车辆",
                list: api.auto_list_available,
                format: item => e('div', { class_name: 'item item-auto outlined' }, [
                    e('div', { class_name: 'main' }, [
                        e('div', { class_name: 'name', text_content: item.name }),
                        e('div', { class_name: 'description', text_content: item.description }),
                    ]),
                    e('div', { class_name: 'side' }, [
                        e('div', { class_name: 'price code', text_content: item.price }),
                        e('button', { text_content: "登录后便可租用", disabled: true }),
                    ]),
                ]),
            },
        ];

        // profiles data
        var profile_makers = {
            guest: () => e('div', { class_name: 'profile' }, [
                e('div', { class_name: 'normal-cursor', text_content: "游客" }),
                e('ul', null, [
                    e('li', { class_name: 'link', text_content: "注册" }, null, { click: () => register() }),
                    e('li', { class_name: 'link', text_content: "登录" }, null, { click: () => login() }),
                ]),
            ]),
            user: () => e('div', { class_name: 'profile' }, [
                e('div', { class_name: 'normal-cursor', text_content: api.name }),
                e('ul', null, [
                    e('li', { class_name: 'link', text_content: "登出" }, null, { click: () => logout() }),
                    e('li', { class_name: 'link', text_content: "个人中心" }, null, { click: () => dashboard() }),
                ]),
            ]),
            admin: () => e('div', { class_name: 'profile' }, [
                e('div', { class_name: 'normal-cursor', text_content: "管理员" }),
                e('ul', null, [
                    e('li', { class_name: 'link', text_content: "登出" }, null, { click: () => logout() }),
                    e('li', { class_name: 'link', text_content: "个人中心" }, null, { click: () => dashboard() }),
                ]),
            ]),
        };

        // setup
        var setup_profile = () => {
            var old_profile = s('nav .profile');
            var new_profile = profile_makers[api.role || 'guest']();
            replace_element(old_profile, new_profile);
        };

        var setup_page_switcher = () => {
            var links = s('nav .links');
            clear_element(links);
            var first;
            pages.filter(page => page.role === api.role).forEach(page => {
                var element = e('li', { class_name: 'link', text_content: page.name });
                links.appendChild(element);
                if (first == null) first = { element, page };

                element.addEventListener('click', () => select_page(element, make_list_page(page)));
            });
            select_page(first.element, make_list_page(first.page));
        };

        var active_page;
        var select_page = (() => {
            var container = s('main > section');
            return (link, view) => {
                if (link != null && link.classList.contains('active')) return;

                var links = sall('nav .links > *');
                links.forEach(l => l === link ? l.classList.add('active') : l.classList.remove('active'));

                clear_element(container);
                container.appendChild(view);
                animate(view, 'slide-up');

                active_page = view;
            };
        })();

        var setup_user = () => {
            setup_profile();
            setup_page_switcher();
        };

        // auto login
        if (localStorage.token) {
            overlay();
            overlay.popup("自动登录中……");
            api.validate(localStorage.token, valid => {
                if (!valid) delete localStorage.token;
                setup_user();
                overlay();
            });
        }
        else {
            setup_user();
            overlay();
        }
    };
});

